import * as XLSX from 'xlsx'
import XLSXWorker from '@utils/xlsx/worker.ts?worker'
import { ReadFileToResult } from '@utils/xlsx/type'

/**
 * Excel工具包，基于js-xlsx
 * @author 木人心
 * @version 1.1.1
 */
export class XLSXUtil {
  /**
   * 【使用worker】读取excel的file文件，并格式化成对象数组
   * @param file file文件
   * @param header
   * @param sheetIndex 获取第一个工作簿
   */
  static workerReadFileTo<R = unknown, H extends string = string> (file: File, header?: H, sheetIndex = 0) {
    return new Promise<ReadFileToResult<R, H>[]>((resolve, reject) => {
      try {
        const xlsxWorker = new XLSXWorker()
        xlsxWorker.postMessage({ file, header, sheetIndex })
        xlsxWorker.onmessage = (e) => {
          switch (e.data.type) {
            case 'Result':
              resolve(e.data.v)
              break
            case 'Error':
              reject(e.data.e)
              break
          }
          xlsxWorker.terminate()
        }
      } catch (e) {
        reject(e)
      }
    })
  }

  /**
   * 读取excel的file文件，并格式化成对象数组
   * @param file file文件
   * @param header
   * @param sheetIndex 获取第一个工作簿
   */
  static async readFileTo <R = unknown, H extends string = string> (file: File, header?: H[], sheetIndex = 0): Promise<ReadFileToResult<R, H>[]> {
    const arrayBuffer = await file.arrayBuffer()
    const workBook = XLSX.read(arrayBuffer)
    return XLSX.utils.sheet_to_json(workBook.Sheets[workBook.SheetNames[sheetIndex]], { header }) as any
  }

  /**
   * 导出excel文件
   * @param sheetData 二维数组
   * @param fileName 文件名称
   * @param sheetName 工作簿名称
   */
  static exportXlSXFileByArray (sheetData: any[][], fileName: string, sheetName = 'Sheet1') {
    const workBook = XLSX.utils.book_new()
    const workSheet = XLSX.utils.aoa_to_sheet(sheetData)
    XLSX.utils.book_append_sheet(workBook, workSheet, sheetName)
    return XLSX.writeFileXLSX(workBook, fileName)
  }

  /**
   * 将一个对象数组格式化为导出文件所需格式
   * @param exportData
   * @param props
   */
  static formatExportData (exportData: Record<string, any>[], props: { key: string, title: string }[]) {
    const keys = []
    const resultData = [props.map(item => {
      keys.push(item.key)
      return item.title
    })]
    const keysLen = keys.length
    for (let i = 0, len = exportData.length; i < len; i++) {
      const row = []
      for (let j = 0; j < keysLen; j++) {
        row[j] = exportData[i][keys[j]]
      }
      resultData.push(row)
    }
    return resultData
  }
}
